﻿using CommonLib.Attr;
using CommonLib.Base;
using CommonLib.CodeEntity;
using CommonLib.Util;
using System.Text.RegularExpressions;

namespace Oracle.Lexer;

[Order(2)]
public class AndLexer : BaseLexer
{
    public override bool Check()
        => Txt.StartsWith("AND ") || Txt.StartsWith("AND(")
        || Txt.StartsWith("WHERE ") || Txt.StartsWith("WHERE(")
        || Txt.StartsWith("ON ") || Txt.StartsWith("ON(");

    protected override BaseCodeEntity Run()
    {
        var entity = new AndCodeEntity();
        var and = string.Empty;
        if (Txt.StartsWith("WHERE"))
        {
            entity.Mark = "WHERE";
            and = Txt[6..].Trim();
        }
        else if (Txt.StartsWith("ON"))
        {
            entity.Mark = "ON";
            and = Txt[2..].Trim();
        }
        else and = Txt[3..].Trim();


        if (and.StartsWith('(') && and.EndsWith(')'))
        {
            and = and[1..^1].Trim();
            entity.HasBracket = true;
        }
        var arr = and.TrimSplit("AND");
        var sub = new List<string>();
        for (int i = 0; i < arr.Length; i++)
        {
            var item = arr[i];
            while (!item.IsFull())
            {
                var next = arr[++i].Trim();
                item = $"{item} AND {next}";
            }
            sub.Add(item);
        }
        for (int i = 0; i < sub.Count; i++)
        {
            var item = sub[i];
            var end = "AND";
            if (item.Contains("BETWEEN"))
            {
                item = $"{item} AND {sub[++i]}";
            }
            if (item.Contains(" EXISTS"))
            {
                end = item[..item.IndexOf("(")].Trim();
                item = Regex.Match(item, "\\((.*)\\)").Result("$1");
            }
            else if (item.Contains(" IN ") || item.Contains(" IN("))
            {
                end = item[..item.IndexOf("(")].Trim();
                var ins = Regex.Match(item, "\\((.*)\\)").Result("$1").Trim();
                if (ins.StartsWith("SELECT")) item = ins;
                else
                {
                    end = item;
                    item = "NONE";
                }
            }
            else if (item.Contains("(+)"))
            {
                var mats = Regex.Matches(item, "([A-Z0-9]+)\\.");
                var list = mats.Select(m => m.Result("$1")).ToList();
                if (item.EndsWith("(+)")) end = string.Join("÷", list);
                else
                {
                    list.Reverse();
                    end = string.Join("÷", list);
                }
                item = item.Replace("(+)", "").Trim();
            }
            var obj = SqlFactory.Create(item).Execute();
            entity.Condition.Add(obj);
            entity.Comments.Add(end);
        }
        return entity;
    }
}
